Eine Einführung
AE Psychologische Methodenlehre, Philipps-Universität Marburg
2023-06-23
https://bit.ly/netz-work-material
Netzwerktheorie: - kausale Interaktion von Symptomen anstatt Syndrome - keine monokausale Erklärung - verschiedene Zustände des komplexen Systems (gesund vs. krank) - stark verbundenes Symptome verstärken sich gegenseitig
graphicalVAR: idiographische NetzwerkemlVAR: Multilevel, ermöglicht Visualisierung von HeterogenitätGIMME: idionomischmgm: Mixed models & zeitlich variierendDSEM (MPlus): komplexe Messmodelle, sehr flexibelBGGM. Bayesianische Methodenpsychonetrics: übergreifende Architekturdynr: Dynamische SystemeHintergrund:
für Modellfitting: simulierte Daten von 25 Personen
Sehr wichtiger Schritt
Einfluss von Datenvorverarbeitung auf Ergebnisse wird oftmals unterschätzt!
Abhängig vom Package
graphicalVAR: Dataframe im Long-Format (jede Beobachtung eine Zeile)GIMME: Listenformat oder individuelle Datenfiles in einem OrdnerAbhängig vom Package:
graphicalVAR: Akzeptiert keine fehlenden Daten. Imputation vorab, etwa univariat über Kalman-Filter aus (na_kalman aus tsImpute)Hoch relevant für die Interpretation!
Mehrere Möglichkeiten:
Explizite Modellierung über continuous-time Modellierung (ctsem)
Auslassen von Effekten über die Nacht in graphicalVAR oder GIMME
Cubic Spline Interpolation (s. Fisher et al., 2017)
Ignorieren 😓
graphicalVARund GIMME: Normalverteilte VariablengraphicalVAR (Espkamp, 2018) ermöglicht idiographische NetzwerkanalysenInterpretation von Heterogenität
Netzwerke sehen durch Schätzunsicherheit oft heterogener aus, als sie tatsächlich sind (Hoekstra et al., 2022; Siepe et al., in prep.)
fit <- graphicalVAR(
data = NULL, # Datensatz
nLambda = 50, # Anzahl von LASSO Parametern, die getestet wird
gamma = 0.5, # EBIC Hyperparameter
scale = TRUE, # z-standardisieren (wichtig für LASSO!)
vars = NULL, # Vektor mit Variablennamen
beepvar = "beep", # Beepvariable
dayvar = "day", # Tagesvariable
idvar = "id" # ID der Person
)boot oder dem bootnet-PackageVorab gestellte Fragen:
Wichtigkeit von nLambda?
Umgang mit EBIC Hyperparameter \(\gamma\)
Einfluss von Detrending
Lags bei graphicalVAR
nLambda?A: Anzahl unterschiedlicher LASSO Regularisierungsparameter. Nicht unter 50 wählen, bei mehr als 50 sollte sich in der Regel nicht allzu viel ändern-
A: Wird gerade bei wenigen Daten oftmals auf 0 gesetzt (s. Mansueto et al, 2022). Dann wird EBIC zum normalen BIC. Abhängig vom Ziel der Untersuchung (Spezifizität vs. Sensitivität).
A: Scheinzusammenhänge zwischen Variablen, die eigentlich nicht miteinander zusammenhängen
graphicalVARA: Bei Spezifikation von Beep-Variable wird der Effekt vom letzten Beep eines Tages auf den nächsten nicht geschätzt
TODO ADD GIMME NETWZERK
graphicalVAR: Schätzt erst temporal, dann contemporaneousGIMME: gerichtet zwischen beobachteten VariablengraphicalVAR: ungerichtet zwischen Residuenhybrid-GIMME (Luo et al., 2023): Verbindet beides! Braucht aber auch mehr DatenZusatzinformation
Die zugrundeliegenden Modelle können mathematisch ineinander transformiert werden (Luo et al., 2023)
Takeaway-Zusammenfassung:
Ein “leeres” Modell für temporal und contemporaneous Zusammenhänge wird auf die Daten angepasst
Gruppe: Iterative Suche nach Verbindungen (anhand von Modifikationsindizes), die Modellfit für bestimmten Teil (etwa 75%) des Samples signifikant (nach Korrektur \(\alpha = 0.05/n\)) verbessern
Pruning von nicht länger signifikanten Pfaden
Subgruppe: Ähnlichkeiten zwischen Individuen werden gesucht anhand Größe der geschätzten Effekte, daraus wird eine sog. Adjacency Matrix kreiert
Walktrap-Algorithmus, um “communities” zu identifizieren
In den entstandenen Subgruppen: Suche nach verbessernden Pfaden für bestimmten Teil (etwa 51%) der Subgruppe (nach Korrektur \(\alpha = 0.05/n\))
Pruning von nicht länger signifikanten Pfaden
Individuell: Suche nach verbessernden Pfaden (\(\alpha = 0.01\)), bis “exzellenter Fit” erreicht ist (RMSEA < .05, SRMR < .05, CFI > .95, NNFI > .95).
\[ \eta_{i,t} = (\color{Red}{A_i} + \color{Blue}{A^S_{i,k}} + \color{orange}{A^g_i})\eta_{i,t} + (\color{Red}{\phi_i} + \color{Blue}{\phi^s_{i,k}} + \color{orange}{\phi^g_i})\eta_{i,t-1} + \zeta_{i,t} \]
\(\eta_{i,t}\): Daten von Individuum \(i\) zum Zeitpunkt \(t\)
\(A\): Contemporaneous Effekte
\(\phi\): Temporale Effekte (VAR-1 Modell)
Orange: Gruppeneffekte
Blau: Subgruppeneffekte
Rot: Individuelle Effekte
\(\zeta_{i,t}\): Residuum von Individuum \(i\) zum Zeitpunkt \(t\)
fit <- gimmeSEM(
data = NULL, # Datenfile
out = NULL, # Outputordner
ar = TRUE, # Autoregressive Effekt schätzen (empfohlen)
plot = TRUE, # Plotten?
subgroup = TRUE, # Subgruppen schätzen?
hybrid = FALSE, # directed & undirected contemporaneous
groupcutoff = .75, # Gruppencutoff
subcutoff = .51, # Subgruppencutoff
...
)Vorab gestellte Fragen:
NA für die Nacht, damit der Nachteffekt nicht geschätzt wirdEffektive Stichprobengröße
Bei Weglassen von Nachteffekten verringert sich die effektive Stichprobengröße!
Wir treffen die notwendigen Vorbereitungen und laden die relevanten Daten. Diese wurden bereits vorab in das notwendige Listenformat umgewandelt und etwas vorverarbeitet, Code dafür ist vorhanden.
file_list <- list.files(here::here("Anwendungs_Workshop/data/individual_files"),
full.names = TRUE)
data_list <- lapply(file_list, read.csv)
# Zeitvariable hinzufügen
data_list <- lapply(data_list, function(x){
x <- x |>
dplyr::mutate(time = dplyr::row_number())
})
saveRDS(data_list, here::here("Anwendungs_Workshop/data/data_list.RDS"))Jedes Individuum hat einen eigenen Eintrag in einer Liste.
Für Personen 1, 5 und 10 ein Histogramm von Dominance erstellen:
Für bessere Übersicht: Deskriptive Statistiken aller Variablen:
# relevante Variablen
rel_vars <- c("Dominance", "Affiliation", "PosAff",
"NegAff", "Stress", "Functioning")
# Berechnen von Mean und SD
desc_list <- list()
for(p in 1:length(data_list)){
desc_list[[p]] <- data_list[[p]] |>
dplyr::summarize(across(all_of(rel_vars),
list(mean = mean, sd = sd), na.rm = TRUE))
}
df_desc <- bind_rows(desc_list, .id = "id")
df_desc |>
dplyr::summarize(across(everything(),
~ round(mean(.), 3))) id Dominance_mean Dominance_sd Affiliation_mean Affiliation_sd PosAff_mean
1 NA 0.491 2.711 1.912 3.333 2.666
PosAff_sd NegAff_mean NegAff_sd Stress_mean Stress_sd Functioning_mean
1 0.61 1.786 0.516 2.425 2.391 1.147
Functioning_sd
1 0.69
Visualisierung von fehlenden Daten: etwa mit naniar-Package
Wir detrenden einen linearen Effekt von Zeit:
# relevante Variablen
rel_vars <- c("Dominance", "Affiliation", "PosAff",
"NegAff", "Stress", "Functioning")
# Loopen über alle p Participants
for(p in 1:length(data_list)){
data_list[[p]] <- fn_detrend(data_list[[p]],
vars = rel_vars,
time_var = "time",
sig_only = FALSE)
}
# Zeitvariable wieder löschn
for(p in 1:length(data_list)){
data_list[[p]] <- subset(data_list[[p]], select = -c(time))
}lapply für die Arbeit mit Listen# lapply statt for loop
mean_list <- lapply(data_list, function(x){
# x: einzelnes Element von data_list
mean(x$Dominance, na.rm = TRUE)
})
# oder als Datensatz verwenden
df_data <- data_list |>
# mit ID abspeichern
tibble::enframe(name = "ID") |>
# in dataframe verwandeln
tidyr::unnest()
# zurück in Liste verwandeln
data_list_new <- split(df_data, df_data$ID)example_data <- gimme::simData
data_list_short <- data_list[1:30]
fit <- gimmeSEM(
data = example_data,
out = "Anwendungs_Workshop/output",
ar = TRUE, # Autoregressive Effekt schätzen (oftmals empfohlen)
plot = TRUE, # Plotten?
subgroup = TRUE, # Subgruppen schätzen?
hybrid = FALSE, # directed & undirected contemporaneous
groupcutoff = .75, # Gruppencutoff
subcutoff = .51 # Subgruppencutoff,
paths = NULL # vorgegebene Gruppenpfade
)
saveRDS(fit, "Anwendungs_Workshop/output/fit.RDS")Alternativ: Fertiges Modell laden
Warning
Achtung: Datenstruktur ist anders als z.B. in qgraph (Reihe: Outcome, Spalte: Prädiktor)
Hauptoutput: summaryFit.csv
Please specify a file id for individual plots. Otherwise, summary plot is presented.
::: fragment
summary_matrix <- read.csv(here("Anwendungs_Workshop/output/summaryPathCountsMatrix.csv"))
summary_matrix V1lag V2lag V3lag V4lag V5lag V6lag V7lag V8lag V9lag V10lag V1 V2 V3 V4 V5
1 25 2 0 0 0 0 0 0 0 0 0 0 14 0 0
2 1 25 0 0 1 0 13 0 0 1 14 0 0 0 0
3 0 0 25 1 0 0 0 1 0 0 1 0 0 12 0
4 0 0 0 25 1 0 1 0 0 25 0 0 0 0 0
5 0 0 0 2 25 2 0 0 25 0 0 0 25 13 0
6 0 0 12 0 0 25 0 0 1 0 1 1 0 1 1
7 2 0 1 0 1 0 25 0 0 0 25 1 0 0 0
8 2 2 1 12 25 0 0 25 0 0 0 1 0 0 0
9 25 0 0 1 0 0 0 13 25 1 0 2 13 0 0
10 1 0 0 0 0 0 0 1 0 25 1 0 0 0 1
V6 V7 V8 V9 V10
1 0 0 25 2 12
2 25 0 0 1 0
3 1 0 25 1 0
4 1 25 2 1 0
5 0 0 0 0 0
6 0 0 1 0 0
7 0 0 12 1 0
8 0 0 0 2 0
9 0 0 0 0 0
10 0 12 0 0 0
::: fragment
Subgroups Plot.pdfsubgroup*k*plot.pdfInterpretation von Subgruppen
Es kann Subgruppen ohne gemeinsames Edge geben! Ähnlichkeit der Pfade allgemein.
GIMME als Input::: fragment
::: fragment - ARI: Adjusted Rand Index. Soll langsam fallen - VI: Variation of Information. Soll langsam steigen.
Mittelwerte und Standardabweichungen von Pfadkoeffizienten betrachten (s. Wright et al., 2022):
indivPathEstimates.csvPunktschätzer & Standardfehler für alle Edgesindiv_path_estimates <- read.csv(here::here("Anwendungs_Workshop/output/indivPathEstimates.csv"))
head(indiv_path_estimates) file lhs op rhs beta se z pval level
1 group_1_1 V1 ~ V1lag 0.6174298 0.05770200 10.70032 0 group
2 group_1_1 V2 ~ V2lag 0.6021825 0.03199423 18.82160 0 group
3 group_1_1 V3 ~ V3lag 0.5831502 0.03767956 15.47656 0 group
4 group_1_1 V4 ~ V4lag 0.5978473 0.03508944 17.03781 0 group
5 group_1_1 V5 ~ V5lag 0.5599982 0.03933617 14.23622 0 group
6 group_1_1 V6 ~ V6lag 0.5313603 0.03863033 13.75500 0 group
sub_membership
1 2
2 2
3 2
4 2
5 2
6 2
Latente Variablen
GIMME mit exogenen Variablen (Beltz & Gates, 2017)
etwa: Zeit, Intervention
CS-GIMME: Confirmatory Subgroups
etwa: wie unterscheiden sich Diagnosegruppen in ihren Dynamiken
ms-GIMME, Auswahl mit AICBeispieldaten aus dem Package:
::: {.panel-tabset}
Implementiert in praktischer Online-App
https://meghan.rbind.io/blog/quarto-slides/ https://www.emilhvitfeldt.com/post/slidecraft-colors-fonts/